home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / rs0422.zip / LEVEL2 / AXL2USER.C < prev    next >
C/C++ Source or Header  |  1990-09-09  |  10KB  |  343 lines

  1. /* User (server) interface to AX.25 level-2 package */
  2.  
  3. #include "buffer.h"
  4. #include "iface.h"
  5. #include "timer.h"
  6. #include "netuser.h"
  7. #include "ax25.h"
  8. #include "ax25l2.h"
  9. #undef NULL
  10. #include "data.h"
  11. #include "l3struc.h"
  12.  
  13.  
  14. #if 0
  15. char *axstates[] = {        /* State name strings for axstat and session cmds */
  16.     "Disconnected",
  17.     "Conn rqst",
  18.     "Frame rej",
  19.     "Disc rqst",
  20.     "Conn (S5)",
  21.     "Conn (S6)",
  22.     "Conn (S7)",
  23.     "Conn (S8)",
  24.     "Conn (S9)",
  25.     "Conn (S10)",
  26.     "Conn (S11)",
  27.     "Conn (S12)",
  28.     "Conn (S13)",
  29.     "Conn (S14)",
  30.     "Conn (S15)",
  31.     "Conn (S16)"
  32. };
  33.  
  34. /* doaxstat -- display status of each existing axcb */
  35. doaxstat(argc, argv)
  36. int argc;
  37. char *argv[];
  38. {
  39.     /*reg*/ static struct axcb *axcb, *axp;
  40.     static char name[120];
  41.     long htol();
  42.  
  43.     if (argc > 1) {
  44.         axcb = (struct axcb *)htol(argv[1]);
  45.         for (axp = links; axp != NULLAXCB; axp = axp->next)
  46.             if (axp == axcb)
  47.                 return state_axl2(axcb);
  48.         printf("Not a valid AXCB\r\n");
  49.         return;
  50.     }
  51.     printf("AXCB state        V SndQ  RcvQ  Ret Timer  Remote\r\n");
  52.     /* One line per axcb */
  53.     for (axcb = links; axcb != NULLAXCB; axcb = axcb->next) {
  54.         if (axcb->alen != 0)
  55.             psax25(name, axcb->path);    /* Destination, digis */
  56.         else
  57.             strcpy(name, "");        /* No destination yet */
  58.     /* Print axcb address, state, protocol version, queue counts and retry
  59.      * count
  60.      */
  61.         printf("%04x %-13.13s%c %-6d%-6d%-4d", (int)axcb,
  62.          axstates[axcb->state -1], (axcb->version == V2) ? '2' : '1',
  63.          axcb->icnt, axcb->rcvcnt, axcb->n2cnt);
  64.     /* Determine whether t1, t3 or neither is running.  Print the remaining
  65.      * count.
  66.      */
  67.         if (axcb->t3.state != TIMER_STOP)
  68.             printf("t3:%-4d", axcb->t3.count);
  69.         else if (axcb->t1.state != TIMER_STOP)
  70.             printf("t1:%-4d", axcb->t1.count);
  71.         else
  72.             printf("------ ");
  73.         printf("%s", name);
  74.         if (axcb->iface != NULL)
  75.             printf(" (%s)", axcb->iface->name);
  76.         printf("\r\n");
  77.     }
  78.     fflush(stdout);
  79. }
  80.  
  81. state_axl2(axcb)
  82. struct axcb *axcb;
  83. {
  84.     static char local[10], remote[120];
  85.     static struct datastr *bp;
  86.     static int ntxq, nrxq;
  87.  
  88.     pax25(local, &axcb->myaddr);
  89.     if (axcb->alen == 0)
  90.         strcpy(remote, "");
  91.     else
  92.         psax25(remote, axcb->path);
  93.     printf("AXCB: %04x  state: %-13.13s  local: %s\r\n", (unsigned)axcb,
  94.      axstates[axcb->state -1], local);
  95.     printf("remote: %s\r\n", remote);
  96.     for (ntxq = 0, bp = axcb->iqueue; bp != NULL; bp = bp->next)
  97.         ntxq++;
  98.     for (nrxq = 0, bp = axcb->rcvq; bp != NULL; bp = bp->nexts)
  99.         nrxq++;
  100.     printf("txq frames: %-2d bytes: %-5d   rxq frames: %-2d bytes: %-5d\r\n",
  101.      ntxq, axcb->icnt, nrxq, axcb->rcvcnt);
  102.     printf("AX.25 vers: %c   n(r): %d   n(s): %d   v(s): %d   last received PID: %02x\r\n",
  103.      (axcb->version == V1) ? '1' : '2', axcb->nr, axcb->ns, axcb->vs,
  104.      axcb->rpid & 0xff);
  105.     printf("T1: %5d/%-5d",
  106.      (axcb->t1.state == TIMER_RUN) ? axcb->t1.count : 0, axcb->t1.start);
  107.     printf("   T2: %5d/%-5d",
  108.      (axcb->t2.state == TIMER_RUN) ? axcb->t2.count : 0, axcb->t2.start);
  109.     printf("   T3: %5d/%-5d\r\n",
  110.      (axcb->t3.state == TIMER_RUN) ? axcb->t3.count : 0, axcb->t3.start);
  111.     fflush(stdout);
  112. }
  113. #endif
  114.  
  115. /* open_ax25 -- create new link (axcb), either in the passive (listen)
  116.  * or active (connect request) state.  "raddr" and "mode" can be NULL,
  117.  * which indicates a wild-card match; any remote address or interface
  118.  * can use the axcb.  Returns pointer to new axcb, or NULL if no axcb
  119.  * was made.
  120.  */
  121. struct axcb *
  122. open_ax25(laddrx,raddr,iface,alen)
  123. struct ax25_addr *laddrx;    /* Local AX25 address (MYCALL) */
  124. struct ax25_addr *raddr;    /* Remote AX25 address (digis optional) */
  125. struct interface *iface;    /* I/O interface */
  126. unsigned char alen;            /* Length of the raddr (path) */
  127. {
  128.     static struct ax25_addr *laddr;
  129.     register struct axcb *axcb;
  130.     struct axcb *lookup_axcb();
  131.     int l2_st_up(), spclev(), l2_window();
  132.     void l2_rx_up(), l2_tx_up();
  133.     extern struct ax25_parms *l2parms;
  134.  
  135.     laddr=laddrx;
  136.  
  137.     if ((laddr == NULL) ||        /* Must have a local address! */
  138.  
  139.     /* If an axcb with exactly the same parameters is already in
  140.      * existance, it constitutes an error.
  141.      */
  142.         (lookup_axcb(laddr, raddr, iface, alen) != NULL) ||
  143.         (spclev() == CRITICAL)) return NULL;    /* No space! */
  144.  
  145.     /* Attempt to allocate an axcb */
  146.     if ((axcb=new_link()) == NULL) return NULL;
  147.  
  148.     /* Put the local address in the axcb */
  149.     bcopy(laddr->call, axcb->myaddr.call, ALEN);
  150.     axcb->myaddr.ssid=laddr->ssid;
  151.  
  152.     /* Put the remote address in the axcb */
  153.     axcb->alen=0;
  154.     if (raddr != NULL) setpath(axcb, raddr, 0, alen);
  155.  
  156.     /* Fill the rest of the axcb */
  157.     axcb->parms = l2parms;        /* Level-2 parameter block */
  158.     axcb->iface = iface;        /* Interface (may be NULL) */
  159.     axcb->state = 1;        /* Disconnected state */
  160.     axcb->r_upcall = l2_rx_up;    /* Upcall handlers */
  161.     axcb->t_upcall = l2_tx_up;
  162.     axcb->s_upcall = l2_st_up;
  163.     axcb->window = l2_window(l2parms); /* Data window */
  164.  
  165. /*    axcb->t1=NULL;
  166.     axcb->t2=NULL;
  167.     axcb->t3=NULL;    /* new_link() Uses calloc(), not malloc() */
  168.  
  169.     axcb->version=axcb->parms->version;  /* Set intial protocol version */
  170.     axcb->n2cnt = axcb->parms->retry;
  171.     /* Put the axcb on the list */
  172.     if (links) axcb->next = links;
  173.     links = axcb;
  174.  
  175.     puthex2("Opened",axcb,"",0);
  176.     return axcb;
  177. }
  178. #if 0
  179. /* reopen_ax25 -- force a change to the connect-request state and
  180.  * optionally change the path.
  181.  */
  182. int
  183. reopen_ax25(axcb, path, alenx)
  184. register struct axcb *axcb;
  185. struct ax25_addr *path;
  186. int alenx;
  187. {
  188.     static int i, alen;
  189.  
  190.     if (axcb == NULLAXCB) return -1;
  191.  
  192.     if (path != NULL) {
  193.         setpath(axcb, path, 0, alen);
  194. /*        for (i=0;i<alen;i++) {
  195.             bcopy(axcb->path[i].call, axcb->pathspec[i].call,ALEN);
  196.             axcb->pathspec[i].ssid=axcb->path[i].ssid;
  197.         }
  198.         axcb->speclen = axcb->alen;
  199. */    }
  200.     axconnect(axcb);
  201.     return 0;
  202. }
  203. #endif
  204. /* recv_ax25 -- called to get received data.  Received data is stored
  205.  * in a single mbuf packet.  If the rx window comes open as a result
  206.  * of the removal of data from the queue, the clear-busy procedure is
  207.  * performed.  If passed "cnt" is zero, returns all data on queue.  On
  208.  * successful return, the pointer pointed to by "bp" points to the
  209.  * data (get the point?)
  210.  * Returns the byte count, or -1 on error.
  211.  */
  212. int
  213. recv_ax25(axcb, bpx, cntx)
  214. register struct axcb *axcb;    /* Link */
  215. struct datastr **bpx;    /* mbuf pointer to fill */
  216. int cntx;        /* Max bytes to return, or 0 for all */
  217. {
  218.     static int i, cnt;
  219.     static struct datastr **bp;
  220.  
  221.     cnt= cntx;
  222.     bp = bpx;    /* bp and bpx point to the same pointer */
  223.     puthex2("Recv",cnt,"For",axcb);
  224.     /* Make sure calling args are OK */
  225.     if (axcb == NULLAXCB || bp == (struct datastr **) NULL) return -1;
  226.  
  227.     if (cnt == 0)        /* Caller wants all the data */
  228.         cnt = axcb->rcvcnt;
  229.     if (axcb->rcvcnt != 0) {
  230.         if (axcb->rcvcnt <= cnt) {    /* Return all the data */
  231.             cnt = axcb->rcvcnt;
  232.             *bp = axcb->rcvq;
  233.             axcb->rcvq = NULL;    /* Empty queue */
  234.         } else {
  235.     /* Make an datastr and fill it */
  236.             if ((*bp = new_buffer(cnt)) == NULL) return -1;
  237.             for (i=0;i<cnt;i++) bappch(*bp,bgetch(&axcb->rcvq));
  238.         }
  239.         axcb->rcvcnt -= cnt;
  240.     /* If we were busy but aren't now, perform the clear-busy procedure */
  241.         if ((axcb->flags & BUSY) && axcb->rcvcnt < axcb->window) {
  242.             axcb->flags &= ~BUSY;
  243.             respond(axcb, clr_busy, 0, 0);
  244.         }
  245.         return cnt;
  246.     }
  247.     /* If call was made when queue is empty, return error */
  248.     return -1;
  249. }
  250.  
  251. /* send_ax25 -- called to send data on a link.  Data is stored on the
  252.  * tx queue as a queue of datastr packets.
  253.  */
  254. int
  255. send_ax25(axcb, bp, pid)
  256. register struct axcb *axcb;    /* Link */
  257. struct datastr *bp;    /* Data to send */
  258. char pid;        /* PID to use */
  259. {
  260.     static struct datastr *mbp; /*, *bp; */
  261.     static struct datastr *qp;
  262.     static struct datastr *qp1;
  263.     static int cnt;
  264.     void sendi();
  265.  
  266.     if (axcb == NULLAXCB) {
  267.         free_pkt(bp);
  268.         return -1;
  269.     }
  270.     if (bp == NULL) return -1;
  271.  
  272.     cnt = buflen(bp);
  273.     puthex2("Send",cnt,"For",axcb);
  274.  
  275.     axcb->icnt += cnt;    /* Update tx queue count */
  276.     /* Find end of tx queue */
  277.     qp1 = NULL;
  278.     for (qp = axcb->iqueue; qp != NULL; qp = qp->next) qp1 = qp;
  279.  
  280.     mbp=new_buffer(1);        /* Get a segment for the PID */
  281.     bappch(mbp,pid);
  282.     mbp=binsert(mbp, bp);        /* Merge PID and data */
  283.     axcb->icnt++;
  284.     /* Put mbuf on end of tx queue */
  285.     if (qp1 == NULL)        /* Queue is empty */
  286.         axcb->iqueue = mbp;
  287.     else
  288.         qp1->next = mbp;
  289.  
  290.     /* Try sending the data; queue it so we can let the application */
  291.     queue(NULL,sendi,1,axcb);    /* fill the window before we TX */
  292.     return 0;
  293. }
  294.  
  295. /* close_ax25 -- "local stop" command.  Issue disconnect on link.
  296.  * Returns 0 if successful, -1 if not.
  297.  */
  298. int
  299. close_ax25(axcb)
  300. register struct axcb *axcb;
  301. {
  302.     puthex2("Close",axcb,"",0);
  303.     if (axcb->state == 1) return -1;    /* Already disconnected */
  304.  
  305.     /* If we are in connect request or disconnect request state, just
  306.      * go to disconnected state and shut down the link.
  307.      */
  308.     if (axcb->state == 2 || axcb->state == 4) {
  309.         axcb->n2cnt = 0;
  310.         actionl2(axcb, 1, -1, 0, 0);
  311.     }
  312.     else    /* Send DISC and go to disconnect request state */
  313.         actionl2(axcb, 4, DISC, 0, CMD+RSTT1+SETT1);
  314.     return 0;
  315. }
  316.  
  317. /* del_ax25 -- delete axcb, freeing its resources */
  318. void
  319. del_ax25(axcb)
  320. register struct axcb *axcb;
  321. {
  322.     static struct axcb *cbp;
  323.     static struct VCS *vc;
  324.  
  325.     puthex2("Delax",axcb,"",0);
  326.     if (!axcb) return;
  327.     /* Find axcb on the list and remove it */
  328.     if (links == axcb) links = links->next;
  329.     else /* Search the rest of the list for this guy */ {
  330.         for (cbp = links; cbp != NULLAXCB; cbp = cbp->next)
  331.             if (axcb == cbp->next) {
  332.                 cbp->next = axcb->next;
  333.                 axcb->next = NULL;
  334.                 break;
  335.             }
  336.     }
  337.     link_reset(axcb);    /* Stop the timers */
  338.     free_queue(&axcb->iqueue);    /* Throw away any queued data */
  339.     free_pkt(axcb->rcvq);
  340.     while (vc=axcb->llcn) set_p(vc,P1,0); /* Discard any remaining VCs */
  341.     free(axcb);        /* Throw away the axcb */
  342. }
  343.